package service

import (
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"github.com/gin-gonic/gin"
	"os"
	"path"
	"strings"
	"tinyGW/app/api/repository"
	"tinyGW/app/api/schemas/req"
	"tinyGW/app/api/schemas/resp"
	"tinyGW/app/models"
	"tinyGW/pkg/plugin/io"
	"tinyGW/pkg/plugin/response"
	"tinyGW/pkg/service/script"
)

type DeviceTypeService interface {
	Add(deviceType *req.DeviceTypeReq) error
	Update(deviceType *req.DeviceTypeReq) error
	Delete(name string) error
	Find(name string) (resp.DeviceTypeResp, error)
	FindAll() ([]resp.DeviceTypeResp, error)
	List(page *req.PageReq) (response.PageResp, error)
	// TODO: 增加其他方法
	AddProperties(deviceTypeName string, deviceProperty *req.DeviceProperty) error
	UpdateProperties(deviceTypeName string, devicePropertyId int, deviceProperty *req.DeviceProperty) error
	DeleteProperties(deviceTypeName string, devicePropertyId int) error
	FindProperty(deviceTypeName string, devicePropertyId int) (models.DeviceProperty, error)
	FindAllProperties(deviceTypeName string) ([]models.DeviceProperty, error)
	Upload(name string, c *gin.Context) (resp.DeviceTypeResp, error)

	// Lua 文件管理
	GetLuaFiles(driver string) (map[string]string, error)         // 获取协议的所有 Lua 文件
	GetLuaFile(driver string, filename string) (string, error)    // 获取单个 Lua 文件内容
	SaveLuaFile(driver string, filename string, content string) error // 保存 Lua 文件
	GetDriverUsage(driver string) ([]string, int64, error)        // 获取协议使用情况（设备类型列表和数量）
	ListDrivers() ([]string, error)                               // 列出所有可用的协议
	
	// 协议测试
	TestProtocol(driver string, messageData string, format string) (interface{}, error) // 测试协议解析
}

type deviceTypeService struct {
	deviceRepository     repository.DeviceRepository
	deviceTypeRepository repository.DeviceTypeRepository
}

func (d deviceTypeService) AddProperties(deviceTypeName string, deviceProperty *req.DeviceProperty) error {
	var model models.DeviceProperty
	response.Copy(&model, deviceProperty)
	err := d.deviceTypeRepository.AddProperties(deviceTypeName, &model)
	if err != nil {
		return err
	}

	deviceType, _ := d.deviceTypeRepository.Find(deviceTypeName)
	d.deviceRepository.DeviceTypeChanged(deviceType)
	return err
}

func (d deviceTypeService) UpdateProperties(deviceTypeName string, devicePropertyId int, deviceProperty *req.DeviceProperty) error {
	var model models.DeviceProperty
	response.Copy(&model, deviceProperty)
	err := d.deviceTypeRepository.UpdateProperties(deviceTypeName, devicePropertyId, &model)
	if err != nil {
		return err
	}

	deviceType, _ := d.deviceTypeRepository.Find(deviceTypeName)
	d.deviceRepository.DeviceTypeChanged(deviceType)
	return err
}

func (d deviceTypeService) DeleteProperties(deviceTypeName string, devicePropertyId int) error {
	err := d.deviceTypeRepository.DeleteProperties(deviceTypeName, devicePropertyId)
	if err != nil {
		return err
	}

	deviceType, _ := d.deviceTypeRepository.Find(deviceTypeName)
	d.deviceRepository.DeviceTypeChanged(deviceType)
	return err
}

func (d deviceTypeService) FindProperty(deviceTypeName string, devicePropertyId int) (models.DeviceProperty, error) {
	return d.deviceTypeRepository.FindProperty(deviceTypeName, devicePropertyId)
}

func (d deviceTypeService) FindAllProperties(deviceTypeName string) ([]models.DeviceProperty, error) {
	return d.deviceTypeRepository.FindAllProperties(deviceTypeName)
}

func (d deviceTypeService) Add(deviceType *req.DeviceTypeReq) error {
	_, err := d.deviceTypeRepository.Find(deviceType.Name)
	if err == nil {
		return fmt.Errorf("仪表 %s <UNK>", deviceType.Name)
	}
	var dv models.DeviceType
	response.Copy(&dv, deviceType)
	return d.deviceTypeRepository.Save(&dv)
}

func (d deviceTypeService) Update(deviceType *req.DeviceTypeReq) error {
	var dv models.DeviceType
	response.Copy(&dv, deviceType)
	return d.deviceTypeRepository.Save(&dv)
}

func (d deviceTypeService) Delete(name string) error {
	return d.deviceTypeRepository.Delete(name)
}

func (d deviceTypeService) Find(name string) (resp.DeviceTypeResp, error) {
	f, err := d.deviceTypeRepository.Find(name)
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("仪表 %s 不存在", name)
	}
	var deviceType resp.DeviceTypeResp
	response.Copy(&deviceType, f)
	return deviceType, nil
}

func (d deviceTypeService) FindAll() ([]resp.DeviceTypeResp, error) {
	fs, err := d.deviceTypeRepository.FindAll()
	if err != nil {
		return nil, err
	}
	var deviceTypes []resp.DeviceTypeResp
	response.Copy(&deviceTypes, fs)
	return deviceTypes, nil
}

func (d deviceTypeService) List(page *req.PageReq) (response.PageResp, error) {
	limit := page.PageSize
	offset := page.PageSize * (page.PageNo - 1)
	list, total, err := d.deviceTypeRepository.List(limit, offset)
	if err != nil {
		return response.PageResp{}, err
	}
	var deviceTypes []req.DeviceTypeReq
	response.Copy(&deviceTypes, list)
	return response.PageResp{
		Count:    total,
		PageNo:   page.PageNo,
		PageSize: page.PageSize,
		Lists:    list,
	}, nil
}

func (d deviceTypeService) Upload(name string, c *gin.Context) (resp.DeviceTypeResp, error) {
	dt, err := d.deviceTypeRepository.Find(name)
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("仪表 %s 不存在", name)
	}
	io.SureExists("plugin")
	dir, err := os.Getwd()
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("获取当前目录失败 %s", err.Error())
	}
	file, err := c.FormFile("FileName")
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("上传失败 %s", err.Error())
	}
	pluginDir := path.Join(dir, "plugin")
	filename := path.Join(pluginDir, file.Filename)
	err = c.SaveUploadedFile(file, filename)
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("保存文件失败 %s", err.Error())
	}
	defer os.Remove(filename)

	err = io.Unzip(filename, pluginDir)
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("解压失败 %s", err.Error())
	}
	filenameWithSuffix := path.Base(filename)
	fileType := path.Ext(filename)
	plugin := strings.TrimSuffix(filenameWithSuffix, fileType)
	dt.Driver = plugin

	propertiesFile := "plugin/" + plugin + "/properties.json"
	if ok := io.PathExists(propertiesFile); ok {
		if data, err := io.ReadFile(propertiesFile); err == nil {
			properties := []models.DeviceProperty{}
			if json.Unmarshal(data, &properties) == nil {
				dt.Properties = properties
			}
		}
	}

	err = d.deviceTypeRepository.Save(&dt)
	if err != nil {
		return resp.DeviceTypeResp{}, fmt.Errorf("保存失败 %s", err.Error())
	}
	var resp resp.DeviceTypeResp
	response.Copy(&resp, dt)
	return resp, nil
}

// GetLuaFiles 获取协议的所有 Lua 文件（文件名 -> 文件内容）
func (d deviceTypeService) GetLuaFiles(driver string) (map[string]string, error) {
	if driver == "" {
		return nil, fmt.Errorf("driver 不能为空")
	}
	
	dir, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("获取当前目录失败: %s", err.Error())
	}
	
	pluginDir := path.Join(dir, "plugin", driver)
	if !io.PathExists(pluginDir) {
		return nil, fmt.Errorf("协议目录不存在: %s", driver)
	}
	
	files := make(map[string]string)
	entries, err := os.ReadDir(pluginDir)
	if err != nil {
		return nil, fmt.Errorf("读取目录失败: %s", err.Error())
	}
	
	for _, entry := range entries {
		if !entry.IsDir() {
			ext := path.Ext(entry.Name())
			// 只读取 .lua 和 .json 文件
			if ext == ".lua" || ext == ".json" {
				filePath := path.Join(pluginDir, entry.Name())
				content, err := os.ReadFile(filePath)
				if err == nil {
					files[entry.Name()] = string(content)
				}
			}
		}
	}
	
	return files, nil
}

// GetLuaFile 获取单个 Lua 文件内容
func (d deviceTypeService) GetLuaFile(driver string, filename string) (string, error) {
	if driver == "" || filename == "" {
		return "", fmt.Errorf("driver 和 filename 不能为空")
	}
	
	dir, err := os.Getwd()
	if err != nil {
		return "", fmt.Errorf("获取当前目录失败: %s", err.Error())
	}
	
	filePath := path.Join(dir, "plugin", driver, filename)
	if !io.PathExists(filePath) {
		return "", fmt.Errorf("文件不存在: %s/%s", driver, filename)
	}
	
	content, err := os.ReadFile(filePath)
	if err != nil {
		return "", fmt.Errorf("读取文件失败: %s", err.Error())
	}
	
	return string(content), nil
}

// SaveLuaFile 保存 Lua 文件
func (d deviceTypeService) SaveLuaFile(driver string, filename string, content string) error {
	if driver == "" || filename == "" {
		return fmt.Errorf("driver 和 filename 不能为空")
	}
	
	// 安全检查：只允许 .lua 和 .json 文件
	ext := path.Ext(filename)
	if ext != ".lua" && ext != ".json" {
		return fmt.Errorf("只允许保存 .lua 和 .json 文件")
	}
	
	// 防止路径遍历攻击
	if strings.Contains(filename, "..") || strings.Contains(driver, "..") {
		return fmt.Errorf("非法的文件路径")
	}
	
	dir, err := os.Getwd()
	if err != nil {
		return fmt.Errorf("获取当前目录失败: %s", err.Error())
	}
	
	pluginDir := path.Join(dir, "plugin", driver)
	if !io.PathExists(pluginDir) {
		// 如果目录不存在，创建它
		if err := os.MkdirAll(pluginDir, 0755); err != nil {
			return fmt.Errorf("创建目录失败: %s", err.Error())
		}
	}
	
	filePath := path.Join(pluginDir, filename)
	if err := os.WriteFile(filePath, []byte(content), 0644); err != nil {
		return fmt.Errorf("保存文件失败: %s", err.Error())
	}
	
	return nil
}

// GetDriverUsage 获取协议使用情况
func (d deviceTypeService) GetDriverUsage(driver string) ([]string, int64, error) {
	if driver == "" {
		return nil, 0, fmt.Errorf("driver 不能为空")
	}
	
	deviceTypes, err := d.deviceTypeRepository.FindByDriver(driver)
	if err != nil {
		return nil, 0, err
	}
	
	names := make([]string, len(deviceTypes))
	for i, dt := range deviceTypes {
		names[i] = dt.Name
	}
	
	return names, int64(len(names)), nil
}

// ListDrivers 列出所有可用的协议（遍历 plugin 目录）
func (d deviceTypeService) ListDrivers() ([]string, error) {
	dir, err := os.Getwd()
	if err != nil {
		return nil, fmt.Errorf("获取当前目录失败: %s", err.Error())
	}
	
	pluginDir := path.Join(dir, "plugin")
	if !io.PathExists(pluginDir) {
		return []string{}, nil
	}
	
	entries, err := os.ReadDir(pluginDir)
	if err != nil {
		return nil, fmt.Errorf("读取目录失败: %s", err.Error())
	}
	
	drivers := []string{}
	for _, entry := range entries {
		if entry.IsDir() {
			// 检查目录中是否有同名的 .lua 文件
			luaFile := path.Join(pluginDir, entry.Name(), entry.Name()+".lua")
			if io.PathExists(luaFile) {
				drivers = append(drivers, entry.Name())
			}
		}
	}
	
	return drivers, nil
}

// TestProtocol 测试协议解析
func (d deviceTypeService) TestProtocol(driver string, messageData string, format string) (interface{}, error) {
	if driver == "" {
		return nil, fmt.Errorf("driver 不能为空")
	}
	if messageData == "" {
		return nil, fmt.Errorf("messageData 不能为空")
	}
	
	// 解析报文数据
	var data []byte
	var err error
	
	switch format {
	case "hex":
		// 移除空格、换行符和制表符
		cleanData := strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(messageData, " ", ""), "\n", ""), "\t", "")
		
		// 验证十六进制格式
		if len(cleanData)%2 != 0 {
			return nil, fmt.Errorf("十六进制数据长度必须是偶数，当前长度: %d", len(cleanData))
		}
		
		data, err = hex.DecodeString(cleanData)
		if err != nil {
			return nil, fmt.Errorf("十六进制数据解析失败: %v (数据: %s)", err, cleanData)
		}
	case "base64":
		data, err = base64.StdEncoding.DecodeString(messageData)
		if err != nil {
			return nil, fmt.Errorf("Base64数据解析失败: %v", err)
		}
	default:
		return nil, fmt.Errorf("不支持的数据格式: %s", format)
	}
	
	// 验证解析后的数据
	if len(data) == 0 {
		return nil, fmt.Errorf("解析后的数据为空")
	}
	
	// 创建 Lua 运行器
	runner := script.NewLuaRunner()
	defer runner.Close()
	
	// 打开协议脚本
	if err := runner.Open(driver); err != nil {
		return nil, fmt.Errorf("打开协议脚本失败: %v", err)
	}
	
	// 构建测试结果
	result := map[string]interface{}{
		"DetectProtocol":         false,
		"ExtractDeviceAddress":   "",
		"AnalysisRx":             nil,
	}
	
	// 1. 测试 DetectProtocol
	if runner.HasFunction("DetectProtocol") {
		if detected := runner.DetectProtocol(data); detected {
			result["DetectProtocol"] = true
		}
	}
	
	// 2. 测试 ExtractDeviceAddress
	if runner.HasFunction("ExtractDeviceAddress") {
		if address := runner.ExtractDeviceAddress(data); address != "" {
			result["ExtractDeviceAddress"] = address
		}
	}
	
	// 3. 测试 AnalysisRx
	if runner.HasFunction("AnalysisRx") {
		// 使用空的设备地址进行测试
		// 注意：AnalysisRxEnhanced 会在内部设置 rxBuf 全局变量
		// 由于没有预定义属性，Lua 脚本返回的变量会被直接创建为新变量
		analysisResult := runner.AnalysisRxEnhanced("", []models.DeviceProperty{}, data, len(data))
		
		// 构建响应结果
		analysisData := map[string]interface{}{
			"Status":       "0",
			"Variable":     []interface{}{},
			"FrameType":    analysisResult.FrameType,
			"NeedResponse": analysisResult.NeedResponse,
			"Response":     []interface{}{},
		}
		
		if !analysisResult.Success {
			analysisData["Status"] = "1"
		}
		
		// 转换变量
		if len(analysisResult.Variables) > 0 {
			variables := make([]interface{}, 0)
			for _, v := range analysisResult.Variables {
				variables = append(variables, map[string]interface{}{
					"name":        v.Name,
					"type":        v.Type,
					"value":       v.Value,
					"description": v.Description,
				})
			}
			analysisData["Variable"] = variables
		}
		
		// 转换响应数据
		if len(analysisResult.Response) > 0 {
			response := make([]interface{}, len(analysisResult.Response))
			for i, b := range analysisResult.Response {
				response[i] = b
			}
			analysisData["Response"] = response
		}
		
		result["AnalysisRx"] = analysisData
	}
	
	return result, nil
}

func NewDeviceTypeService(deviceRepository repository.DeviceRepository, deviceTypeRepository repository.DeviceTypeRepository) DeviceTypeService {
	return &deviceTypeService{
		deviceRepository:     deviceRepository,
		deviceTypeRepository: deviceTypeRepository,
	}
}
